//
//	File Name   :	bmpLoader.cpp
//	Description :	bmpLoader implementation file.
//	Author		:	William McVicar
//  Mail		:	mcvicar.william@gmail.com
//

//  Precompiled Header
#include "CommonDefines.h"

//  Library Includes
#include <Windows.h>

//  External Includes
#include <FreeImage.h>

//  Local Includes
#include "../ProteinFramework.h"
#include "../IFileSystem.h"
#include "../Image.h"

//  This includes
#include "bmpLoader.h"

//	Macros
#define MCHAR2(a, b) (a | (b << 8))
#define MCHAR4(a, b, c, d) (a | (b << 8) | (c << 16) | (d << 24))

//  Static Variables

//  Static Function Prototypes

//  Implementation

namespace Protein
{

CBMP::CBMP()
{

}

CBMP::~CBMP()
{

}

bool CBMP::Load( const c8* _szFilename, Image& _rImage )
{
	std::string path;
	char buf[ PROTEIN_MAX_PATH ];
	strcpy( buf, _szFilename );
	strcat( buf, ".bmp" );
	if( IFileSystem::FILESYSTEM_ERROR_FILE_NOT_FOUND == fileSystem().FileExists( buf, path ) )
		return false;

	FILE* pFile = NULL;
	if( !fileSystem().Open( path.c_str(), g_kBINARY_READ_ONLY, &pFile, true ) )
		return false;

	BITMAPFILEHEADER header;
	BITMAPINFOHEADER info;
	u8* imageData;

	memset( &header, 0, sizeof( BITMAPFILEHEADER ) );
	memset( &info,   0, sizeof( BITMAPINFOHEADER ) );

	unsigned char textureColors = 0;   

	fileSystem().Read((u8*)&header, sizeof(BITMAPFILEHEADER), 1, pFile);

	if(header.bfType != BITMAP_ID)
	{
		fileSystem().Close(pFile);
		return false;
	}

	fileSystem().Read((u8*)&info, sizeof(info), 1, pFile);

	if(info.biSizeImage == 0)
		info.biSizeImage = info.biWidth * info.biHeight * 3;

	fseek(pFile, header.bfOffBits, SEEK_SET);

	imageData = reinterpret_cast< u8* >( malloc(info.biSizeImage) );

	if(!imageData)
	{
		free(imageData);
		fileSystem().Close(pFile);
		return false;
	}

	fileSystem().Read(imageData, 1, info.biSizeImage, pFile);

	if(!imageData)
	{
		fileSystem().Close(pFile);
		return false;
	}

	// Bitmaps are saved in BGR format so we will make the image RGB by...
	for(int index = 0; index < (int)info.biSizeImage; index+=3)
	{
		textureColors = imageData[index];
		imageData[index] = imageData[index + 2];
		imageData[index + 2] = textureColors;
	}

	fileSystem().Close(pFile);     

	ePixelFormat pf;
	switch( info.biBitCount )
	{
		case 24: pf = PF_RGB8;  break;
		case 32: pf = PF_RGBA8; break;
	}

	_rImage.Init( info.biWidth, info.biHeight, 0, pf, 1, path, imageData, info.biSizeImage );

	return true;
}

}